
Namespace Validation
    <AttributeUsage(AttributeTargets.Property, AllowMultiple:=False, Inherited:=False)> Public Class RangeValidatorAttribute
        Inherits BaseValidatorAttribute

#Region " Declarations "

        Private _enumLowerRangeBoundaryType As RangeBoundaryType = RangeBoundaryType.Exclusive
        Private _enumRequiredEntry As RequiredEntry = RequiredEntry.No
        Private _enumUpperRangeBoundaryType As RangeBoundaryType = RangeBoundaryType.Exclusive
        Private _objLowerValue As IComparable
        Private _objUpperValue As IComparable

#End Region

#Region " Properties "

        Public ReadOnly Property LowerRangeBoundaryType() As RangeBoundaryType
            Get
                Return _enumLowerRangeBoundaryType
            End Get
        End Property

        Public ReadOnly Property LowerValue() As IComparable
            Get
                Return _objLowerValue
            End Get
        End Property

        Public ReadOnly Property RequiredEntry() As RequiredEntry
            Get
                Return _enumRequiredEntry
            End Get
        End Property

        Public ReadOnly Property UpperRangeBoundaryType() As RangeBoundaryType
            Get
                Return _enumUpperRangeBoundaryType
            End Get
        End Property

        Public ReadOnly Property UpperValue() As IComparable
            Get
                Return _objUpperValue
            End Get
        End Property

#End Region

#Region " Constructor "

        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As Double, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As Double, ByVal enumRequiredEntry As RequiredEntry)
            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _objLowerValue = objLowerValue
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _objUpperValue = objUpperValue
            _enumRequiredEntry = enumRequiredEntry
        End Sub

        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As Integer, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As Integer, ByVal enumRequiredEntry As RequiredEntry)
            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _objLowerValue = objLowerValue
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _objUpperValue = objUpperValue
            _enumRequiredEntry = enumRequiredEntry
        End Sub

        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As Long, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As Long, ByVal enumRequiredEntry As RequiredEntry)
            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _objLowerValue = objLowerValue
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _objUpperValue = objUpperValue
            _enumRequiredEntry = enumRequiredEntry
        End Sub

        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As Short, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As Short, ByVal enumRequiredEntry As RequiredEntry)
            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _objLowerValue = objLowerValue
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _objUpperValue = objUpperValue
            _enumRequiredEntry = enumRequiredEntry
        End Sub

        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As Single, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As Single, ByVal enumRequiredEntry As RequiredEntry)
            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _objLowerValue = objLowerValue
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _objUpperValue = objUpperValue
            _enumRequiredEntry = enumRequiredEntry
        End Sub

        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As String, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As String, ByVal enumRequiredEntry As RequiredEntry)
            _objLowerValue = objLowerValue
            _objUpperValue = objUpperValue
            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _enumRequiredEntry = enumRequiredEntry
        End Sub

        ''' <summary>
        '''HACK - New Feature - fixed constructor to support date and decimal types since these are not allowed in a attributes constructor
        '''There is some restriction on the data types that can be used as attribute parameters. 
        '''Parameters can be any integral data type (Byte, Short, Integer, Long) or floating point data type (Single and Double), as well as Char, String, Boolean, an enumerated type, or System.Type. 
        '''Thus, Date, Decimal, Object, and structured types cannot be used as parameters.
        '''This is a simple work around.
        ''' </summary>
        Public Sub New(ByVal enumLowerRangeBoundaryType As RangeBoundaryType, ByVal objLowerValue As String, ByVal enumUpperRangeBoundaryType As RangeBoundaryType, ByVal objUpperValue As String, ByVal enumRequiredEntry As RequiredEntry, ByVal enumConvertToType As ConvertToType)

            Select Case enumConvertToType

                Case ConvertToType.Date
                    _objLowerValue = CType(objLowerValue, Date)
                    _objUpperValue = CType(objUpperValue, Date)

                Case ConvertToType.Decimal
                    _objLowerValue = CType(objLowerValue, Decimal)
                    _objUpperValue = CType(objUpperValue, Decimal)

                Case Else
                    Throw New ArgumentOutOfRangeException("enumConvertToType", "This ConverToType has not yet been programmed, value passed was: " & enumConvertToType.ToString)
            End Select

            _enumLowerRangeBoundaryType = enumLowerRangeBoundaryType
            _enumUpperRangeBoundaryType = enumUpperRangeBoundaryType
            _enumRequiredEntry = enumRequiredEntry
        End Sub

#End Region

#Region " Methods "

        Public Overrides Function Create(ByVal strPropertyName As String) As Validator
            Return New Validator(AddressOf Validation.ComparisonValidationRules.InRangeRule, New RangeRuleEventArgs(Me, strPropertyName), RuleType.Attribute)
        End Function

#End Region

    End Class

End Namespace
